/*******************************************************************************
 * Copyright (C) 2010 Devin Samarin.
 * 
 * This file is part of the SUIT Toolkit.
 * 
 * The SUIT Toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The SUIT Toolkit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the SUIT Toolkit.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package suit.ui;


/**
 * A Widget that emits a signal when clicked on. Button can hold any just about
 * any other Widget as its child. The most commonly used child is a Label, and
 * there are convenience methods to help you just create a button with the given
 * text automatically, notably the Button(String) constructor.
 * 
 * A Button only renders the first child.
 * 
 * @author Devin Samarin
 * 
 */
public class Button extends Widget {

	protected boolean active = false;
	protected boolean pressed = false;

	protected int focusable = FOCUS_TRUE;

	/**
	 * Create an "empty" button to use as a Container. You'll need to add() the
	 * Widget which will be the Button's child.
	 */
	public Button() {
		initialize();
	}

	/**
	 * Create a button with a Label as its child. Simply specify the text you
	 * want for the Label and a Button will be created accordingly.
	 * 
	 * @param text
	 *            the text you wish on the Label that will be created in the
	 *            Button
	 */
	public Button(String text) {
		this();
		Label label = new Label(text);
		label.align = Label.CENTER | Label.VCENTER;
		add(label);
	}

	private void initialize() {
		active = false;
	}

	/**
	 * Set the state of the Button. This is better used in the ToggleButton
	 * class and its descendants.
	 * 
	 * @param active
	 *            whether or not the Button is active (down)
	 */
	public void setActive(boolean active) {
		this.active = active;
		invalidate(this);
		touch();
	}

	/**
	 * Return the state of the Button. This is better used in the ToggleButton
	 * class and its descendants.
	 * 
	 * @return whether or not the Button is active (down)
	 */
	public boolean getActive() {
		return active;
	}

	protected boolean onExpose(Event e) {

		e.theme.drawButton(e.graphics, this, allocation, active);

		if (children != null) {
			Widget w = ((Widget) children.firstElement());
			w.sizeAllocate(new Rectangle(allocation.x + 10, allocation.y + 10,
					allocation.w - 20, allocation.h - 20));
			w.registerEvent(e);
		}
		return true;
	}

	protected boolean onLongPress(int x, int y) {
		System.out.println("Long press: " + x + ", " + y);
		return false;
	}

	protected boolean onPointerPressed(Event e) {
		if (localizeEvent(e) != null) {
			pressed = true;
			setActive(true);
			if (pressHandler != null)
				pressHandler.onPressed(this);
		}
		return false;
	}

	protected boolean onPointerReleased(Event e) {
		if( pressed ) activate();
		pressed = false;
		if (this.active) {
			setActive(false);
			if (releaseHandler != null)
				releaseHandler.onReleased(this);
		}
		return false;
	}

	protected boolean onLeaveNotify(Event e) {
		if (pressed) {
			setActive(false);
		}
		return false;
	}

	protected boolean onEnterNotify(Event e) {
		if (pressed) {
			setActive(true);
		}
		return false;
	}

	public void activate() {
		if (clickHandler != null)
			clickHandler.onClicked(this);
	}

	protected Rectangle getRequisition() {
		Rectangle r = ((Widget) children.firstElement()).getRequisition();
		r.w += 20;
		r.h += 20;
		return r;
	}

	protected Clicked clickHandler;

	/**
	 * Hook up a handler to receive Button.Clicked events on this Button. See
	 * Button.Clicked for a detailed discussion of how to connect signals.
	 * 
	 * @param handler
	 *            Button.Clicked interface to receive events
	 */
	public void connect(Clicked handler) {
		clickHandler = handler;
	}

	protected Pressed pressHandler;

	/**
	 * Hook up a handler to receive Button.Clicked events on this Button. See
	 * Button.Clicked for a detailed discussion of how to connect signals.
	 * 
	 * @param handler
	 *            Button.Clicked interface to receive events
	 */
	public void connect(Pressed handler) {
		pressHandler = handler;
	}

	protected Released releaseHandler;

	/**
	 * Hook up a handler to receive Button.Clicked events on this Button. See
	 * Button.Clicked for a detailed discussion of how to connect signals.
	 * 
	 * @param handler
	 *            Button.Clicked interface to receive events
	 */
	public void connect(Released handler) {
		releaseHandler = handler;
	}

	/**
	 * Event generated when a user presses and releases a Button, causing it to
	 * activate.
	 * 
	 * @author Devin Samarin
	 * 
	 */
	public interface Clicked {
		public void onClicked(Button source);
	}

	/**
	 * Event generated when a user presses a Button.
	 * 
	 * @author Devin Samarin
	 * 
	 */
	public interface Pressed {
		public void onPressed(Button source);
	}

	/**
	 * Event generated when a user released a Button.
	 * 
	 * @author Devin Samarin
	 * 
	 */
	public interface Released {
		public void onReleased(Button source);
	}

}